package com.xm.clj.underserver.webSocket;

import com.alibaba.fastjson.JSON;
import com.xm.clj.underserver.bean.GetMessage;
import com.xm.clj.underserver.utils.AsyncTask;
import com.xm.clj.underserver.utils.DBUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@ServerEndpoint(value = "/ws/oneToMany/{user}/{room}")
@Component
public class OneToManyWebSocket {

    AsyncTask asyncTask = new AsyncTask();

    private static final Logger log = LoggerFactory.getLogger(OneToManyWebSocket.class);

    /** 记录当前在线连接数 */
    private static AtomicInteger onlineCount = new AtomicInteger(0);

    /** 存放所有在线的客户端 */
//    private static Map<String, Session> clients = new ConcurrentHashMap<>();


    /** 存放用户id 与 session */
    public static Map<String,Session> usersMap = new ConcurrentHashMap<>();

    /**key room id value 用户表**/
    public static Map<String, List<Session>> rooms = new ConcurrentHashMap<>();

    /** key room id  value 卧底**/
    public static Map<String, List<String>> roomUnder = new ConcurrentHashMap<>();

    /**key room id  value vote**/
    public static Map<String,List<String>> curVote = new ConcurrentHashMap<>();

    public static Map<String,Integer> curPlayers = new ConcurrentHashMap<>();

    /** key  room id    value  words  (平民  卧底)**/
    public static Map<String,List<String>> roomWords = new ConcurrentHashMap<>();

    /** key  room id  value owner id**/
    public static Map<String,String> roomOwner = new ConcurrentHashMap<>();


    private static final String LOCK = "lock";

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "user")String user, @PathParam(value = "room")String room) {
        System.out.println("start create socket");
        System.out.println("room: "+room);
        onlineCount.incrementAndGet(); // 在线数加1
//        clients.put(userId, session);
        List<Session> userInRoom = null;
        // TODO 为玩家分配序号
        synchronized (LOCK) {

            if (rooms.containsKey(room)) {
                System.out.println("contain");
                userInRoom = rooms.get(room);
            }
            else{
                System.out.println("not contain");
                userInRoom = new ArrayList<>();
            }
            userInRoom.add(session);
            int userIndex = userInRoom.size();
            System.out.println("userindex:"+userIndex);
            rooms.put(room,userInRoom);
            System.out.println("rooms "+rooms.get(room).size());
            // 记录数据库
            DBUtils.db_enterRoom(user,room,""+userIndex);
            // 更新所有玩家的ui

            GetMessage getMessage = new GetMessage();
            getMessage.setId("7");
            getMessage.setMes(""+userIndex);
            sendBack(JSON.toJSONString(getMessage),session);
            updateUIUser(room,userInRoom);
        }
        System.out.println("id "+user + "   room "+room);
        usersMap.put(user,session);
        log.info("有新连接加入：{}，当前在线人数为：{}", user, onlineCount.get());
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session, @PathParam(value = "user")String user, @PathParam(value = "room")String room) {
        onlineCount.decrementAndGet(); // 在线数减1
//        clients.remove(session.getId());
        usersMap.remove(user);
        // 移除玩家
        rooms.get(room).remove(session);
        // 从数据库删除
        DBUtils.db_outRoom(user,room);
        // 是否更换房主
        changeOwner(user,room);
        log.info("有一连接关闭：{}，当前在线人数为：{}", user, onlineCount.get());

    }

    private void changeOwner(String user, String room) {
        if (OneToManyWebSocket.roomOwner.get(room).equals(user)){
            List<Map<String,Object>> ans = DBUtils.findUsers(room);
            if (ans.size()==0){
                // 没有玩家了,删除房间
                usersMap.remove(room);
                rooms.remove(room);
                roomUnder.remove(room);
                curVote.remove(room);
                curPlayers.remove(room);
                roomWords.remove(room);
                roomOwner.remove(room);
            }
            else{
                String newId = (String) ans.get(0).get("userId");
                Session newOwner = usersMap.get(newId);
                GetMessage getMessage = new GetMessage();
                getMessage.setId("12");
                newOwner.getAsyncRemote().sendText(JSON.toJSONString(getMessage));
            }
        }
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message
     *            客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session, @PathParam(value = "user")String user) {
            log.info("服务端收到客户端[{}]的消息:{}", user, message);
//        this.sendMessage(message, session);
        // 解析用户发送给服务端的信息
        asyncTask.readInfo(message,user);

    }

    @OnError
    public void onError(Session session, Throwable error, @PathParam(value = "user")String user, @PathParam(value = "room")String room) {
        log.error("发生错误");
        rooms.get(room).remove(session);
        error.printStackTrace();
        onlineCount.decrementAndGet(); // 在线数减1
        usersMap.remove(user);
        // 是否更换房主
        changeOwner(user,room);
    }

    private static void updateUIUser(String room,List<Session> users){
        StringBuilder stb = new StringBuilder();
        String username = "";
        List<Map<String,Object>> list = DBUtils.findGameUser(room);
        for (Map<String,Object> map:list){
            stb.append((String) map.get("userindex"));
            stb.append(",");
            // 查用户名
            System.out.println("name: " +(String) map.get("userId"));
            username = DBUtils.findUsername((String) map.get("userId"));
            stb.append(username);
            stb.append(";");
        }
        String ans = stb.toString();
        System.out.println("ans:"+ans);
        GetMessage getMessage = new GetMessage();
        getMessage.setId("9");
        getMessage.setMes(ans.substring(0,ans.length()-1));
        for (Session to:users){
            to.getAsyncRemote().sendText(JSON.toJSONString(getMessage));
        }
    }


//    private static void sendMessage(String message, Session fromSession) {
//        for (Map.Entry<String, Session> sessionEntry : clients.entrySet()) {
//            Session toSession = sessionEntry.getValue();
//            // 排除掉自己
//            if (!fromSession.getId().equals(toSession.getId())) {
//                log.info("服务端给客户端[{}]发送消息{}", toSession.getId(), message);
//                toSession.getAsyncRemote().sendText(message);
//            }
//        }
//    }

    private void SendIndexToOther(String message,Session fromSession, List<Session> users,String user){
        // 查用户名
        String username = DBUtils.findUsername(user);
        GetMessage getMessage = new GetMessage();
        getMessage.setId("9");
        getMessage.setMes(message+";"+username);

        for (Session toSession: users){
            toSession.getAsyncRemote().sendText(message);
        }
    }

    private void sendBack(String message, Session toSession){
        toSession.getAsyncRemote().sendText(message);
        log.info("数据发送成功");
    }

    public static void sendMessageToMany(String message,List<Session> toSessions){
        for (Session toSession:toSessions){
            toSession.getAsyncRemote().sendText(message);
        }
    }

    public static void sendToAll(String message,String room){
        List<Session> to = rooms.get(room);
        for (Session session:to){
            session.getAsyncRemote().sendText(message);
        }
    }

    public static void sendChatToOther(GetMessage message,String user,String room){
        List<Session> users = rooms.get(room);
        GetMessage getMessage = new GetMessage();
        getMessage.setId("10");
        getMessage.setFrom(user);
        // index -》 id
        String curId = DBUtils.db_index2Id(user,room);
        Session curSession = usersMap.get(curId);
        getMessage.setMes(message.getMes());
        String json = JSON.toJSONString(getMessage);
        for (Session toSession:rooms.get(room)){
            if (!toSession.equals(curSession)){
                toSession.getAsyncRemote().sendText(json);
            }
        }
    }

    /**
     * @param message 投票信息，序号
     * @param user    玩家id
     */
    public static void sendRoomVoteMessage(String message,String user){
        Map<String,Object> res = DBUtils.db_findUserInfo(user);
        String room = (String) res.get("roomId");
        String index = (String) res.get("userindex");
        List<Session> users = rooms.get(room);
        Session fromSession = usersMap.get(user);
        GetMessage getMessage = new GetMessage();
        getMessage.setId("8");
        getMessage.setMes(message);
        getMessage.setFrom(index);
        String ans = JSON.toJSONString(getMessage);
        // 发送消息给其他人
        for (Session toSession : users){
            if (!fromSession.equals(toSession)){
                toSession.getAsyncRemote().sendText(ans);
            }
        }
    }

}
